#include "MyFileSystem.h"
#include <iostream>
#include <dirent.h>  //文件系统库
#include <sys/stat.h>  //文件系统库

MyFileSystem::MyFileSystem(const std::string &path)
{
    FileInfo * Info = new FileInfo(path);
    TreeNode * rootPath = new TreeNode(Info);
    rootPath->Connect(tree.GetRoot());
    ExploreDir(rootPath,Info);
}

MyFileSystem::~MyFileSystem()
{
    tree.SetFreeFunc(Free);
}

void MyFileSystem::show()
{
    tree.SetPrintFunc(Print);
    tree.show();
}

bool Compare(void *p1, void *p2)
{
    FileInfo * s1 = ( FileInfo *) p1;
    FileInfo * s2 = ( FileInfo *) p1;

    return s1->LeafName == s2->LeafName;
}

void MyFileSystem::FindByFileName(const std::string& name)
{
    FileInfo * tmp = new FileInfo(name);
    tree.SetCompareFunc(Compare);
    DoubleLinkList list = tree.FindByElement(tmp);
    for(size_t i = 0; i < list.Size(); i++)
    {
        TreeNode *node = (TreeNode *)*list.FindByIndex(i);
        FileInfo * path  = (FileInfo *)node->GetData();
        // while(node->GetParent() != nullptr && node->GetParent() != tree.GetRoot())
        // {
        //     FileInfo * path2 = (FileInfo *)node->GetParent()->GetData();
        //     path->name = path2->name + "/" + path->name;
        //     node = node->GetParent();
        // }
        std::cout << path->name << std::endl;
    }
    delete tmp;
}

std::string DoubleToStr(double n, int fixed = 3)  //保留的位数
{
    std::string s = std::to_string(n);
    return s.substr(0, s.find('.') + fixed + 1);
}

std::string Transform(long size)
{
    // char s[100];
    // int i = 0;
    // while(size > 0)
    // {
    //     s[i] = size % 10 + '0';
    //     i++;
    //     size /= 10;
    // }

    // std::string result = "";
    // for(int index = i - 1; index >= 0; index--)
    // {
    //     result += s[index];
    // }
    // return result;

    if(size < 1024)
    {
        return std::to_string(size) + "B";
    }
    else if(size < 1024 * 1024)
    {
        return DoubleToStr(1.0 * size / 1024) + "KB";
    }
    else if(size < 1024 * 1024 * 1024)
    {
        return DoubleToStr(1.0 * size / 1024 / 1024) + "MB";
    }
    else
    {
        return DoubleToStr(1.0 * size / 1024 / 1024 / 1024) + "GB";
    }
}

void MyFileSystem::Free(void *p)
{
    FileInfo * s = (FileInfo *) p;
    delete s;
}

void MyFileSystem::Print(void *p)
{
    FileInfo * s = (FileInfo *) p;
    printf("%-50s ",s->LeafName.c_str());
    if(s->fileSize != 0)
        printf(" size: %s",Transform(s->fileSize).c_str());
    printf("\n");
}

void MyFileSystem::ExploreDir(TreeNode *parent, FileInfo* path)
{
    DIR *dir = opendir((path->name + path->AppendName).c_str());  //打开文件夹
    if (dir == nullptr)
    {
        std::cout << "文件夹路径有误!\n";
        return;
    }

    //dirent *d = readdir(dir);  //读取文件夹内容
    dirent *d = nullptr;
    while( (d = readdir(dir)) != nullptr)  //循环读取文件夹内容
    {
        std::string dname(d->d_name);
        if(dname != "." && dname != "..")
        {
            FileInfo* Info = new FileInfo(path->name);
            Info->LeafName = dname;
            TreeNode* node = new TreeNode(Info);
            node->Connect(parent);

            if(d->d_type == DT_DIR)
            {
                Info->AppendName = path->AppendName + "/" + dname;
                ExploreDir(node, Info);
            }
            else
            {
                struct stat s;
                Info->AppendName = path->AppendName + "/" + dname;
                stat((Info->name + Info->AppendName).c_str(),&s);//根据路径获取文件信息
                Info->fileSize = s.st_size;
                node->SetData(Info);
            }
        }
    }

    closedir(dir);  //关闭文件夹
}




